home *** CD-ROM | disk | FTP | other *** search
/ PC/CD Gamer UK 120 / CD Gamer Issue 120 (March 2003) (Disc 2).ISO / mods / Q2_Codered / codeRED1_0.exe / Data1.cab / r_model.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-12-07  |  26.9 KB  |  1,204 lines

  1. /*
  2. Copyright (C) 1997-2001 Id Software, Inc.
  3.  
  4. This program is free software; you can redistribute it and/or
  5. modify it under the terms of the GNU General Public License
  6. as published by the Free Software Foundation; either version 2
  7. of the License, or (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  12.  
  13. See the GNU General Public License for more details.
  14.  
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  18.  
  19. */
  20. // r_model.c -- model loading and caching
  21.  
  22. #include "r_local.h"
  23.  
  24. model_t    *loadmodel;
  25. int        modfilelen;
  26.  
  27. void Mod_LoadSpriteModel (model_t *mod, void *buffer);
  28. void Mod_LoadBrushModel (model_t *mod, void *buffer);
  29. void Mod_LoadAliasModel (model_t *mod, void *buffer);
  30. model_t *Mod_LoadModel (model_t *mod, qboolean crash);
  31.  
  32. byte    mod_novis[MAX_MAP_LEAFS/8];
  33.  
  34. #define    MAX_MOD_KNOWN    512
  35. model_t    mod_known[MAX_MOD_KNOWN];
  36. int        mod_numknown;
  37.  
  38. // the inline * models from the current map are kept seperate
  39. model_t    mod_inline[MAX_MOD_KNOWN];
  40.  
  41. int        registration_sequence;
  42.  
  43. /*
  44. ===============
  45. Mod_PointInLeaf
  46. ===============
  47. */
  48. mleaf_t *Mod_PointInLeaf (vec3_t p, model_t *model)
  49. {
  50.     mnode_t        *node;
  51.     float        d;
  52.     cplane_t    *plane;
  53.     
  54.     if (!model || !model->nodes)
  55.         Com_Printf ("Mod_PointInLeaf: bad model");
  56.  
  57.     node = model->nodes;
  58.     while (1)
  59.     {
  60.         if (node->contents != -1)
  61.             return (mleaf_t *)node;
  62.         plane = node->plane;
  63.         d = DotProduct (p,plane->normal) - plane->dist;
  64.         if (d > 0)
  65.             node = node->children[0];
  66.         else
  67.             node = node->children[1];
  68.     }
  69.     
  70.     return NULL;    // never reached
  71. }
  72.  
  73.  
  74. /*
  75. ===================
  76. Mod_DecompressVis
  77. ===================
  78. */
  79. byte *Mod_DecompressVis (byte *in, model_t *model)
  80. {
  81.     static byte    decompressed[MAX_MAP_LEAFS/8];
  82.     int        c;
  83.     byte    *out;
  84.     int        row;
  85.  
  86.     row = (model->vis->numclusters+7)>>3;    
  87.     out = decompressed;
  88.  
  89.     if (!in)
  90.     {    // no vis info, so make all visible
  91.         while (row)
  92.         {
  93.             *out++ = 0xff;
  94.             row--;
  95.         }
  96.         return decompressed;        
  97.     }
  98.  
  99.     do
  100.     {
  101.         if (*in)
  102.         {
  103.             *out++ = *in++;
  104.             continue;
  105.         }
  106.     
  107.         c = in[1];
  108.         in += 2;
  109.         while (c)
  110.         {
  111.             *out++ = 0;
  112.             c--;
  113.         }
  114.     } while (out - decompressed < row);
  115.     
  116.     return decompressed;
  117. }
  118.  
  119. /*
  120. ==============
  121. Mod_ClusterPVS
  122. ==============
  123. */
  124. byte *Mod_ClusterPVS (int cluster, model_t *model)
  125. {
  126.     if (cluster == -1 || !model->vis)
  127.         return mod_novis;
  128.     return Mod_DecompressVis ( (byte *)model->vis + model->vis->bitofs[cluster][DVIS_PVS],
  129.         model);
  130. }
  131.  
  132.  
  133. //===============================================================================
  134.  
  135. /*
  136. ================
  137. Mod_Modellist_f
  138. ================
  139. */
  140. void Mod_Modellist_f (void)
  141. {
  142.     int        i;
  143.     model_t    *mod;
  144.     int        total;
  145.  
  146.     total = 0;
  147.     Com_Printf ("Loaded models:\n");
  148.     for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++)
  149.     {
  150.         if (!mod->name[0])
  151.             continue;
  152.         Com_Printf ("%8i : %s\n",mod->extradatasize, mod->name);
  153.         total += mod->extradatasize;
  154.     }
  155.     Com_Printf ("Total resident: %i\n", total);
  156. }
  157.  
  158. /*
  159. ===============
  160. Mod_Init
  161. ===============
  162. */
  163. void Mod_Init (void)
  164. {
  165.     memset (mod_novis, 0xff, sizeof(mod_novis));
  166. }
  167.  
  168.  
  169.  
  170. /*
  171. ==================
  172. Mod_ForName
  173.  
  174. Loads in a model for the given name
  175. ==================
  176. */
  177. model_t *Mod_ForName (char *name, qboolean crash)
  178. {
  179.     model_t    *mod;
  180.     unsigned *buf;
  181.     int        i;
  182.     
  183.     if (!name[0])
  184.         Com_Error (ERR_DROP, "Mod_ForName: NULL name");
  185.         
  186.     //
  187.     // inline models are grabbed only from worldmodel
  188.     //
  189.     if (name[0] == '*')
  190.     {
  191.         i = atoi(name+1);
  192.         if (i < 1 || !r_worldmodel || i >= r_worldmodel->numsubmodels)
  193.             Com_Error (ERR_DROP, "bad inline model number");
  194.         return &mod_inline[i];
  195.     }
  196.  
  197.     //
  198.     // search the currently loaded models
  199.     //
  200.     for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
  201.     {
  202.         if (!mod->name[0])
  203.             continue;
  204.         if (!strcmp (mod->name, name) )
  205.             return mod;
  206.     }
  207.     
  208.     //
  209.     // find a free model slot spot
  210.     //
  211.     for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
  212.     {
  213.         if (!mod->name[0])
  214.             break;    // free spot
  215.     }
  216.     if (i == mod_numknown)
  217.     {
  218.         if (mod_numknown == MAX_MOD_KNOWN)
  219.             Com_Error (ERR_DROP, "mod_numknown == MAX_MOD_KNOWN");
  220.         mod_numknown++;
  221.     }
  222.     strcpy (mod->name, name);
  223.     
  224.     //
  225.     // load the file
  226.     //
  227.     modfilelen = FS_LoadFile (mod->name, &buf);
  228.     if (!buf)
  229.     {
  230.         if (crash)
  231.             Com_Error (ERR_DROP, "Mod_NumForName: %s not found", mod->name);
  232.         memset (mod->name, 0, sizeof(mod->name));
  233.         return NULL;
  234.     }
  235.     
  236.     loadmodel = mod;
  237.  
  238.     //
  239.     // fill it in
  240.     //
  241.  
  242.  
  243.     // call the apropriate loader
  244.     
  245.     switch (LittleLong(*(unsigned *)buf))
  246.     {
  247.     case IDALIASHEADER:
  248.         loadmodel->extradata = Hunk_Begin (0x200000);
  249.         Mod_LoadAliasModel (mod, buf);
  250.         break;
  251.         
  252.     case IDSPRITEHEADER:
  253.         loadmodel->extradata = Hunk_Begin (0x10000);
  254.         Mod_LoadSpriteModel (mod, buf);
  255.         break;
  256.     
  257.     case IDBSPHEADER:
  258.         loadmodel->extradata = Hunk_Begin (0x1000000);
  259.         Mod_LoadBrushModel (mod, buf);
  260.         break;
  261.  
  262.     default:
  263.         Com_Error (ERR_DROP,"Mod_NumForName: unknown fileid for %s", mod->name);
  264.         break;
  265.     }
  266.  
  267.     loadmodel->extradatasize = Hunk_End ();
  268.  
  269.     FS_FreeFile (buf);
  270.  
  271.     return mod;
  272. }
  273.  
  274. /*
  275. ===============================================================================
  276.  
  277.                     BRUSHMODEL LOADING
  278.  
  279. ===============================================================================
  280. */
  281.  
  282. byte    *mod_base;
  283.  
  284.  
  285. /*
  286. =================
  287. Mod_LoadLighting
  288. =================
  289. */
  290. void Mod_LoadLighting (lump_t *l)
  291. {
  292.     if (!l->filelen)
  293.     {
  294.         loadmodel->lightdata = NULL;
  295.         return;
  296.     }
  297.     loadmodel->lightdata = Hunk_Alloc ( l->filelen);    
  298.     memcpy (loadmodel->lightdata, mod_base + l->fileofs, l->filelen);
  299. }
  300.  
  301.  
  302. /*
  303. =================
  304. Mod_LoadVisibility
  305. =================
  306. */
  307. void Mod_LoadVisibility (lump_t *l)
  308. {
  309.     int        i;
  310.  
  311.     if (!l->filelen)
  312.     {
  313.         loadmodel->vis = NULL;
  314.         return;
  315.     }
  316.     loadmodel->vis = Hunk_Alloc ( l->filelen);    
  317.     memcpy (loadmodel->vis, mod_base + l->fileofs, l->filelen);
  318.  
  319.     loadmodel->vis->numclusters = LittleLong (loadmodel->vis->numclusters);
  320.     for (i=0 ; i<loadmodel->vis->numclusters ; i++)
  321.     {
  322.         loadmodel->vis->bitofs[i][0] = LittleLong (loadmodel->vis->bitofs[i][0]);
  323.         loadmodel->vis->bitofs[i][1] = LittleLong (loadmodel->vis->bitofs[i][1]);
  324.     }
  325. }
  326.  
  327.  
  328. /*
  329. =================
  330. Mod_LoadVertexes
  331. =================
  332. */
  333. void Mod_LoadVertexes (lump_t *l)
  334. {
  335.     dvertex_t    *in;
  336.     mvertex_t    *out;
  337.     int            i, count;
  338.  
  339.     in = (void *)(mod_base + l->fileofs);
  340.     if (l->filelen % sizeof(*in))
  341.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  342.     count = l->filelen / sizeof(*in);
  343.     out = Hunk_Alloc ( count*sizeof(*out));    
  344.  
  345.     loadmodel->vertexes = out;
  346.     loadmodel->numvertexes = count;
  347.  
  348.     for ( i=0 ; i<count ; i++, in++, out++)
  349.     {
  350.         out->position[0] = LittleFloat (in->point[0]);
  351.         out->position[1] = LittleFloat (in->point[1]);
  352.         out->position[2] = LittleFloat (in->point[2]);
  353.     }
  354. }
  355.  
  356. /*
  357. =================
  358. RadiusFromBounds
  359. =================
  360. */
  361. float RadiusFromBounds (vec3_t mins, vec3_t maxs)
  362. {
  363.     int        i;
  364.     vec3_t    corner;
  365.  
  366.     for (i=0 ; i<3 ; i++)
  367.     {
  368.         corner[i] = fabs(mins[i]) > fabs(maxs[i]) ? fabs(mins[i]) : fabs(maxs[i]);
  369.     }
  370.  
  371.     return VectorLength (corner);
  372. }
  373.  
  374.  
  375. /*
  376. =================
  377. Mod_LoadSubmodels
  378. =================
  379. */
  380. void Mod_LoadSubmodels (lump_t *l)
  381. {
  382.     dmodel_t    *in;
  383.     mmodel_t    *out;
  384.     int            i, j, count;
  385.  
  386.     in = (void *)(mod_base + l->fileofs);
  387.     if (l->filelen % sizeof(*in))
  388.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  389.     count = l->filelen / sizeof(*in);
  390.     out = Hunk_Alloc ( count*sizeof(*out));    
  391.  
  392.     loadmodel->submodels = out;
  393.     loadmodel->numsubmodels = count;
  394.  
  395.     for ( i=0 ; i<count ; i++, in++, out++)
  396.     {
  397.         for (j=0 ; j<3 ; j++)
  398.         {    // spread the mins / maxs by a pixel
  399.             out->mins[j] = LittleFloat (in->mins[j]) - 1;
  400.             out->maxs[j] = LittleFloat (in->maxs[j]) + 1;
  401.         }
  402.         out->radius = RadiusFromBounds (out->mins, out->maxs);
  403.         out->headnode = LittleLong (in->headnode);
  404.         out->firstface = LittleLong (in->firstface);
  405.         out->numfaces = LittleLong (in->numfaces);
  406.     }
  407. }
  408.  
  409. /*
  410. =================
  411. Mod_LoadEdges
  412. =================
  413. */
  414. void Mod_LoadEdges (lump_t *l)
  415. {
  416.     dedge_t *in;
  417.     medge_t *out;
  418.     int     i, count;
  419.  
  420.     in = (void *)(mod_base + l->fileofs);
  421.     if (l->filelen % sizeof(*in))
  422.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  423.     count = l->filelen / sizeof(*in);
  424.     out = Hunk_Alloc ( (count + 1) * sizeof(*out));    
  425.  
  426.     loadmodel->edges = out;
  427.     loadmodel->numedges = count;
  428.  
  429.     for ( i=0 ; i<count ; i++, in++, out++)
  430.     {
  431.         out->v[0] = (unsigned short)LittleShort(in->v[0]);
  432.         out->v[1] = (unsigned short)LittleShort(in->v[1]);
  433.     }
  434. }
  435.  
  436. /*
  437. =================
  438. Mod_LoadTexinfo
  439. =================
  440. */
  441. void Mod_LoadTexinfo (lump_t *l)
  442. {
  443.     texinfo_t *in;
  444.     mtexinfo_t *out, *step;
  445.     int     i, j, count;
  446.     char    name[MAX_QPATH];
  447.     int        next;
  448.  
  449.     in = (void *)(mod_base + l->fileofs);
  450.     if (l->filelen % sizeof(*in))
  451.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  452.     count = l->filelen / sizeof(*in);
  453.     out = Hunk_Alloc ( count*sizeof(*out));    
  454.  
  455.     loadmodel->texinfo = out;
  456.     loadmodel->numtexinfo = count;
  457.  
  458.     for ( i=0 ; i<count ; i++, in++, out++)
  459.     {
  460.         for (j=0 ; j<8 ; j++)
  461.             out->vecs[0][j] = LittleFloat (in->vecs[0][j]);
  462.  
  463.         out->flags = LittleLong (in->flags);
  464.         next = LittleLong (in->nexttexinfo);
  465.         if (next > 0)
  466.             out->next = loadmodel->texinfo + next;
  467.         else
  468.             out->next = NULL;
  469.  
  470.         Com_sprintf (name, sizeof(name), "textures/%s.wal", in->texture);
  471.         out->image = GL_FindImage (name, it_wall);
  472.     }
  473.  
  474.     // count animation frames
  475.     for (i=0 ; i<count ; i++)
  476.     {
  477.         out = &loadmodel->texinfo[i];
  478.         out->numframes = 1;
  479.         for (step = out->next ; step && step != out ; step=step->next)
  480.             out->numframes++;
  481.     }
  482. }
  483.  
  484. /*
  485. ================
  486. CalcSurfaceExtents
  487.  
  488. Fills in s->texturemins[] and s->extents[]
  489. ================
  490. */
  491. void CalcSurfaceExtents (msurface_t *s)
  492. {
  493.     float    mins[2], maxs[2], val;
  494.     int        i,j, e;
  495.     mvertex_t    *v;
  496.     mtexinfo_t    *tex;
  497.     int        bmins[2], bmaxs[2];
  498.  
  499.     mins[0] = mins[1] = 999999;
  500.     maxs[0] = maxs[1] = -99999;
  501.  
  502.     tex = s->texinfo;
  503.     
  504.     for (i=0 ; i<s->numedges ; i++)
  505.     {
  506.         e = loadmodel->surfedges[s->firstedge+i];
  507.         if (e >= 0)
  508.             v = &loadmodel->vertexes[loadmodel->edges[e].v[0]];
  509.         else
  510.             v = &loadmodel->vertexes[loadmodel->edges[-e].v[1]];
  511.         
  512.         for (j=0 ; j<2 ; j++)
  513.         {
  514.             val = v->position[0] * tex->vecs[j][0] + 
  515.                 v->position[1] * tex->vecs[j][1] +
  516.                 v->position[2] * tex->vecs[j][2] +
  517.                 tex->vecs[j][3];
  518.             if (val < mins[j])
  519.                 mins[j] = val;
  520.             if (val > maxs[j])
  521.                 maxs[j] = val;
  522.         }
  523.     }
  524.  
  525.     for (i=0 ; i<2 ; i++)
  526.     {    
  527.         bmins[i] = floor(mins[i]/16);
  528.         bmaxs[i] = ceil(maxs[i]/16);
  529.  
  530.         s->texturemins[i] = bmins[i] * 16;
  531.         s->extents[i] = (bmaxs[i] - bmins[i]) * 16;
  532.     }
  533. }
  534.  
  535.  
  536. void GL_BuildPolygonFromSurface(msurface_t *fa);
  537. void GL_CreateSurfaceLightmap (msurface_t *surf);
  538. void GL_CreateSurfaceStainmap (msurface_t *surf);
  539. void GL_EndBuildingLightmaps (void);
  540. void GL_BeginBuildingLightmaps (model_t *m);
  541.  
  542. /*
  543. =================
  544. Mod_LoadFaces
  545. =================
  546. */
  547. void Mod_LoadFaces (lump_t *l)
  548. {
  549.     dface_t        *in;
  550.     msurface_t     *out;
  551.     int            i, count, surfnum;
  552.     int            planenum, side;
  553.     int            ti;
  554.  
  555.     in = (void *)(mod_base + l->fileofs);
  556.     if (l->filelen % sizeof(*in))
  557.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  558.     count = l->filelen / sizeof(*in);
  559.     out = Hunk_Alloc ( count*sizeof(*out));    
  560.  
  561.     loadmodel->surfaces = out;
  562.     loadmodel->numsurfaces = count;
  563.  
  564.     currentmodel = loadmodel;
  565.  
  566.     GL_BeginBuildingLightmaps (loadmodel);
  567.  
  568.     for ( surfnum=0 ; surfnum<count ; surfnum++, in++, out++)
  569.     {
  570.         out->firstedge = LittleLong(in->firstedge);
  571.         out->numedges = LittleShort(in->numedges);        
  572.         out->flags = 0;
  573.         out->polys = NULL;
  574.  
  575.         planenum = LittleShort(in->planenum);
  576.         side = LittleShort(in->side);
  577.         if (side)
  578.             out->flags |= SURF_PLANEBACK;            
  579.  
  580.         out->plane = loadmodel->planes + planenum;
  581.  
  582.         ti = LittleShort (in->texinfo);
  583.         if (ti < 0 || ti >= loadmodel->numtexinfo)
  584.             Com_Error (ERR_DROP, "MOD_LoadBmodel: bad texinfo number");
  585.         out->texinfo = loadmodel->texinfo + ti;
  586.  
  587.         CalcSurfaceExtents (out);
  588.  
  589.     // lighting info
  590.  
  591.         for (i=0 ; i<MAXLIGHTMAPS ; i++)
  592.             out->styles[i] = in->styles[i];
  593.         i = LittleLong(in->lightofs);
  594.  
  595.         if (i == -1)
  596.             out->samples = NULL;
  597.         else
  598.             out->samples = loadmodel->lightdata + i;
  599.         out->stainsamples = NULL;
  600.  
  601.     // set the drawing flags
  602.         if (out->texinfo->flags & SURF_WARP)
  603.         {
  604.             out->flags |= SURF_DRAWTURB;
  605.             for (i=0 ; i<2 ; i++)
  606.             {
  607.                 out->extents[i] = 16384;
  608.                 out->texturemins[i] = -8192;
  609.             }
  610.             GL_SubdivideSurface (out);    // cut up polygon for warps
  611.         }
  612.  
  613.         // create lightmaps and polygons
  614.         if ( !SurfaceHasNoLightmap(out) ) 
  615.         {
  616.             GL_CreateSurfaceLightmap (out);
  617.             GL_CreateSurfaceStainmap (out);
  618.         }
  619.  
  620.         if (! (out->texinfo->flags & SURF_WARP) ) 
  621.             GL_BuildPolygonFromSurface(out);
  622.  
  623.     }
  624.  
  625.     GL_EndBuildingLightmaps ();
  626. }
  627.  
  628.  
  629. /*
  630. =================
  631. Mod_SetParent
  632. =================
  633. */
  634. void Mod_SetParent (mnode_t *node, mnode_t *parent)
  635. {
  636.     node->parent = parent;
  637.     if (node->contents != -1)
  638.         return;
  639.     Mod_SetParent (node->children[0], node);
  640.     Mod_SetParent (node->children[1], node);
  641. }
  642.  
  643. /*
  644. =================
  645. Mod_LoadNodes
  646. =================
  647. */
  648. void Mod_LoadNodes (lump_t *l)
  649. {
  650.     int            i, j, count, p;
  651.     dnode_t        *in;
  652.     mnode_t     *out;
  653.  
  654.     in = (void *)(mod_base + l->fileofs);
  655.     if (l->filelen % sizeof(*in))
  656.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  657.     count = l->filelen / sizeof(*in);
  658.     out = Hunk_Alloc ( count*sizeof(*out));    
  659.  
  660.     loadmodel->nodes = out;
  661.     loadmodel->numnodes = count;
  662.  
  663.     for ( i=0 ; i<count ; i++, in++, out++)
  664.     {
  665.         for (j=0 ; j<3 ; j++)
  666.         {
  667.             out->minmaxs[j] = LittleShort (in->mins[j]);
  668.             out->minmaxs[3+j] = LittleShort (in->maxs[j]);
  669.         }
  670.     
  671.         p = LittleLong(in->planenum);
  672.         out->plane = loadmodel->planes + p;
  673.  
  674.         out->firstsurface = LittleShort (in->firstface);
  675.         out->numsurfaces = LittleShort (in->numfaces);
  676.         out->contents = -1;    // differentiate from leafs
  677.  
  678.         for (j=0 ; j<2 ; j++)
  679.         {
  680.             p = LittleLong (in->children[j]);
  681.             if (p >= 0)
  682.                 out->children[j] = loadmodel->nodes + p;
  683.             else
  684.                 out->children[j] = (mnode_t *)(loadmodel->leafs + (-1 - p));
  685.         }
  686.     }
  687.     
  688.     Mod_SetParent (loadmodel->nodes, NULL);    // sets nodes and leafs
  689. }
  690.  
  691. /*
  692. =================
  693. Mod_LoadLeafs
  694. =================
  695. */
  696. void Mod_LoadLeafs (lump_t *l)
  697. {
  698.     dleaf_t     *in;
  699.     mleaf_t     *out;
  700.     int            i, j, count, p;
  701.  
  702.     in = (void *)(mod_base + l->fileofs);
  703.     if (l->filelen % sizeof(*in))
  704.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  705.     count = l->filelen / sizeof(*in);
  706.     out = Hunk_Alloc ( count*sizeof(*out));    
  707.  
  708.     loadmodel->leafs = out;
  709.     loadmodel->numleafs = count;
  710.  
  711.     for ( i=0 ; i<count ; i++, in++, out++)
  712.     {
  713.         for (j=0 ; j<3 ; j++)
  714.         {
  715.             out->minmaxs[j] = LittleShort (in->mins[j]);
  716.             out->minmaxs[3+j] = LittleShort (in->maxs[j]);
  717.         }
  718.  
  719.         p = LittleLong(in->contents);
  720.         out->contents = p;
  721.  
  722.         out->cluster = LittleShort(in->cluster);
  723.         out->area = LittleShort(in->area);
  724.  
  725.         out->firstmarksurface = loadmodel->marksurfaces +
  726.             LittleShort(in->firstleafface);
  727.         out->nummarksurfaces = LittleShort(in->numleaffaces);
  728.     }    
  729. }
  730.  
  731. /*
  732. =================
  733. Mod_LoadMarksurfaces
  734. =================
  735. */
  736. void Mod_LoadMarksurfaces (lump_t *l)
  737. {    
  738.     int        i, j, count;
  739.     short        *in;
  740.     msurface_t **out;
  741.     
  742.     in = (void *)(mod_base + l->fileofs);
  743.     if (l->filelen % sizeof(*in))
  744.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  745.     count = l->filelen / sizeof(*in);
  746.     out = Hunk_Alloc ( count*sizeof(*out));    
  747.  
  748.     loadmodel->marksurfaces = out;
  749.     loadmodel->nummarksurfaces = count;
  750.  
  751.     for ( i=0 ; i<count ; i++)
  752.     {
  753.         j = LittleShort(in[i]);
  754.         if (j < 0 ||  j >= loadmodel->numsurfaces)
  755.             Com_Error (ERR_DROP, "Mod_ParseMarksurfaces: bad surface number");
  756.         out[i] = loadmodel->surfaces + j;
  757.     }
  758. }
  759.  
  760. /*
  761. =================
  762. Mod_LoadSurfedges
  763. =================
  764. */
  765. void Mod_LoadSurfedges (lump_t *l)
  766. {    
  767.     int        i, count;
  768.     int        *in, *out;
  769.     
  770.     in = (void *)(mod_base + l->fileofs);
  771.     if (l->filelen % sizeof(*in))
  772.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  773.     count = l->filelen / sizeof(*in);
  774.     if (count < 1 || count >= MAX_MAP_SURFEDGES)
  775.         Com_Error (ERR_DROP, "MOD_LoadBmodel: bad surfedges count in %s: %i",
  776.         loadmodel->name, count);
  777.  
  778.     out = Hunk_Alloc ( count*sizeof(*out));    
  779.  
  780.     loadmodel->surfedges = out;
  781.     loadmodel->numsurfedges = count;
  782.  
  783.     for ( i=0 ; i<count ; i++)
  784.         out[i] = LittleLong (in[i]);
  785. }
  786.  
  787.  
  788. /*
  789. =================
  790. Mod_LoadPlanes
  791. =================
  792. */
  793. void Mod_LoadPlanes (lump_t *l)
  794. {
  795.     int            i, j;
  796.     cplane_t    *out;
  797.     dplane_t     *in;
  798.     int            count;
  799.     int            bits;
  800.     
  801.     in = (void *)(mod_base + l->fileofs);
  802.     if (l->filelen % sizeof(*in))
  803.         Com_Error (ERR_DROP, "MOD_LoadBmodel: funny lump size in %s",loadmodel->name);
  804.     count = l->filelen / sizeof(*in);
  805.     out = Hunk_Alloc ( count*sizeof(*out));    
  806.     
  807.     loadmodel->planes = out;
  808.     loadmodel->numplanes = count;
  809.  
  810.     for ( i=0 ; i<count ; i++, in++, out++)
  811.     {
  812.         bits = 0;
  813.         for (j=0 ; j<3 ; j++)
  814.         {
  815.             out->normal[j] = LittleFloat (in->normal[j]);
  816.             if (out->normal[j] < 0)
  817.                 bits |= 1<<j;
  818.         }
  819.  
  820.         out->dist = LittleFloat (in->dist);
  821.         out->type = LittleLong (in->type);
  822.         out->signbits = bits;
  823.     }
  824. }
  825.  
  826. /*
  827. =================
  828. Mod_LoadBrushModel
  829. =================
  830. */
  831. void Mod_LoadBrushModel (model_t *mod, void *buffer)
  832. {
  833.     int            i;
  834.     dheader_t    *header;
  835.     mmodel_t     *bm;
  836.     
  837.     loadmodel->type = mod_brush;
  838.     if (loadmodel != mod_known)
  839.         Com_Error (ERR_DROP, "Loaded a brush model after the world");
  840.  
  841.     header = (dheader_t *)buffer;
  842.  
  843.     i = LittleLong (header->version);
  844.     if (i != BSPVERSION)
  845.         Com_Error (ERR_DROP, "Mod_LoadBrushModel: %s has wrong version number (%i should be %i)", mod->name, i, BSPVERSION);
  846.  
  847. // swap all the lumps
  848.     mod_base = (byte *)header;
  849.  
  850.     for (i=0 ; i<sizeof(dheader_t)/4 ; i++)
  851.         ((int *)header)[i] = LittleLong ( ((int *)header)[i]);
  852.  
  853. // load into heap
  854.     
  855.     Mod_LoadVertexes (&header->lumps[LUMP_VERTEXES]);
  856.     Mod_LoadEdges (&header->lumps[LUMP_EDGES]);
  857.     Mod_LoadSurfedges (&header->lumps[LUMP_SURFEDGES]);
  858.     Mod_LoadLighting (&header->lumps[LUMP_LIGHTING]);
  859.     Mod_LoadPlanes (&header->lumps[LUMP_PLANES]);
  860.     Mod_LoadTexinfo (&header->lumps[LUMP_TEXINFO]);
  861.     Mod_LoadFaces (&header->lumps[LUMP_FACES]);
  862.     Mod_LoadMarksurfaces (&header->lumps[LUMP_LEAFFACES]);
  863.     Mod_LoadVisibility (&header->lumps[LUMP_VISIBILITY]);
  864.     Mod_LoadLeafs (&header->lumps[LUMP_LEAFS]);
  865.     Mod_LoadNodes (&header->lumps[LUMP_NODES]);
  866.     Mod_LoadSubmodels (&header->lumps[LUMP_MODELS]);
  867.     mod->numframes = 2;        // regular and alternate animation
  868.     
  869. //
  870. // set up the submodels
  871. //
  872.     for (i=0 ; i<mod->numsubmodels ; i++)
  873.     {
  874.         model_t    *starmod;
  875.  
  876.         bm = &mod->submodels[i];
  877.         starmod = &mod_inline[i];
  878.  
  879.         *starmod = *loadmodel;
  880.         
  881.         starmod->firstmodelsurface = bm->firstface;
  882.         starmod->nummodelsurfaces = bm->numfaces;
  883.         starmod->firstnode = bm->headnode;
  884.         if (starmod->firstnode >= loadmodel->numnodes)
  885.             Com_Error (ERR_DROP, "Inline model %i has bad firstnode", i);
  886.  
  887.         VectorCopy (bm->maxs, starmod->maxs);
  888.         VectorCopy (bm->mins, starmod->mins);
  889.         starmod->radius = bm->radius;
  890.     
  891.         if (i == 0)
  892.             *loadmodel = *starmod;
  893.  
  894.         starmod->numleafs = bm->visleafs;
  895.     }
  896. }
  897.  
  898. /*
  899. ==============================================================================
  900.  
  901. ALIAS MODELS
  902.  
  903. ==============================================================================
  904. */
  905.  
  906. /*
  907. =================
  908. Mod_LoadAliasModel
  909. =================
  910. */
  911. void Mod_LoadAliasModel (model_t *mod, void *buffer)
  912. {
  913.     int                    i, j;
  914.     dmdl_t                *pinmodel, *pheader;
  915.     dstvert_t            *pinst, *poutst;
  916.     dtriangle_t            *pintri, *pouttri;
  917.     daliasframe_t        *pinframe, *poutframe;
  918.     int                    *pincmd, *poutcmd;
  919.     int                    version;
  920.  
  921.     pinmodel = (dmdl_t *)buffer;
  922.  
  923.     version = LittleLong (pinmodel->version);
  924.     if (version != ALIAS_VERSION)
  925.         Com_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
  926.                  mod->name, version, ALIAS_VERSION);
  927.  
  928.     pheader = Hunk_Alloc (LittleLong(pinmodel->ofs_end));
  929.     
  930.     // byte swap the header fields and sanity check
  931.     for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
  932.         ((int *)pheader)[i] = LittleLong (((int *)buffer)[i]);
  933.  
  934.     if (pheader->skinheight > MAX_LBM_HEIGHT)
  935.         Com_Error (ERR_DROP, "model %s has a skin taller than %d", mod->name,
  936.                    MAX_LBM_HEIGHT);
  937.  
  938.     if (pheader->num_xyz <= 0)
  939.         Com_Error (ERR_DROP, "model %s has no vertices", mod->name);
  940.  
  941.     if (pheader->num_xyz > MAX_VERTS)
  942.         Com_Error (ERR_DROP, "model %s has too many vertices", mod->name);
  943.  
  944.     if (pheader->num_st <= 0)
  945.         Com_Error (ERR_DROP, "model %s has no st vertices", mod->name);
  946.  
  947.     if (pheader->num_tris <= 0)
  948.         Com_Error (ERR_DROP, "model %s has no triangles", mod->name);
  949.  
  950.     if (pheader->num_frames <= 0)
  951.         Com_Error (ERR_DROP, "model %s has no frames", mod->name);
  952.  
  953. //
  954. // load base s and t vertices (not used in gl version)
  955. //
  956.     pinst = (dstvert_t *) ((byte *)pinmodel + pheader->ofs_st);
  957.     poutst = (dstvert_t *) ((byte *)pheader + pheader->ofs_st);
  958.  
  959.     for (i=0 ; i<pheader->num_st ; i++)
  960.     {
  961.         poutst[i].s = LittleShort (pinst[i].s);
  962.         poutst[i].t = LittleShort (pinst[i].t);
  963.     }
  964.  
  965. //
  966. // load triangle lists
  967. //
  968.     pintri = (dtriangle_t *) ((byte *)pinmodel + pheader->ofs_tris);
  969.     pouttri = (dtriangle_t *) ((byte *)pheader + pheader->ofs_tris);
  970.  
  971.     for (i=0 ; i<pheader->num_tris ; i++)
  972.     {
  973.         for (j=0 ; j<3 ; j++)
  974.         {
  975.             pouttri[i].index_xyz[j] = LittleShort (pintri[i].index_xyz[j]);
  976.             pouttri[i].index_st[j] = LittleShort (pintri[i].index_st[j]);
  977.         }
  978.     }
  979.  
  980. //
  981. // load the frames
  982. //
  983.     for (i=0 ; i<pheader->num_frames ; i++)
  984.     {
  985.         pinframe = (daliasframe_t *) ((byte *)pinmodel 
  986.             + pheader->ofs_frames + i * pheader->framesize);
  987.         poutframe = (daliasframe_t *) ((byte *)pheader 
  988.             + pheader->ofs_frames + i * pheader->framesize);
  989.  
  990.         memcpy (poutframe->name, pinframe->name, sizeof(poutframe->name));
  991.         for (j=0 ; j<3 ; j++)
  992.         {
  993.             poutframe->scale[j] = LittleFloat (pinframe->scale[j]);
  994.             poutframe->translate[j] = LittleFloat (pinframe->translate[j]);
  995.         }
  996.         // verts are all 8 bit, so no swapping needed
  997.         memcpy (poutframe->verts, pinframe->verts, 
  998.             pheader->num_xyz*sizeof(dtrivertx_t));
  999.  
  1000.     }
  1001.  
  1002.     mod->type = mod_alias;
  1003.  
  1004.     //
  1005.     // load the glcmds
  1006.     //
  1007.     pincmd = (int *) ((byte *)pinmodel + pheader->ofs_glcmds);
  1008.     poutcmd = (int *) ((byte *)pheader + pheader->ofs_glcmds);
  1009.     for (i=0 ; i<pheader->num_glcmds ; i++)
  1010.         poutcmd[i] = LittleLong (pincmd[i]);
  1011.  
  1012.  
  1013.     // register all skins - this is where it should be!!!!
  1014.     memcpy ((char *)pheader + pheader->ofs_skins, (char *)pinmodel + pheader->ofs_skins,
  1015.         pheader->num_skins*MAX_SKINNAME);
  1016.  
  1017.     for (i=0 ; i<pheader->num_skins ; i++)
  1018.         mod->skins[i] = GL_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
  1019.  
  1020.     mod->mins[0] = -32;
  1021.     mod->mins[1] = -32;
  1022.     mod->mins[2] = -32;
  1023.     mod->maxs[0] = 32;
  1024.     mod->maxs[1] = 32;
  1025.     mod->maxs[2] = 32;
  1026. }
  1027.  
  1028. /*
  1029. ==============================================================================
  1030.  
  1031. SPRITE MODELS
  1032.  
  1033. ==============================================================================
  1034. */
  1035.  
  1036. /*
  1037. =================
  1038. Mod_LoadSpriteModel
  1039. =================
  1040. */
  1041. void Mod_LoadSpriteModel (model_t *mod, void *buffer)
  1042. {
  1043.     dsprite_t    *sprin, *sprout;
  1044.     int            i;
  1045.  
  1046.     sprin = (dsprite_t *)buffer;
  1047.     sprout = Hunk_Alloc (modfilelen);
  1048.  
  1049.     sprout->ident = LittleLong (sprin->ident);
  1050.     sprout->version = LittleLong (sprin->version);
  1051.     sprout->numframes = LittleLong (sprin->numframes);
  1052.  
  1053.     if (sprout->version != SPRITE_VERSION)
  1054.         Com_Error (ERR_DROP, "%s has wrong version number (%i should be %i)",
  1055.                  mod->name, sprout->version, SPRITE_VERSION);
  1056.  
  1057.     if (sprout->numframes > MAX_MD2SKINS)
  1058.         Com_Error (ERR_DROP, "%s has too many frames (%i > %i)",
  1059.                  mod->name, sprout->numframes, MAX_MD2SKINS);
  1060.  
  1061.     // byte swap everything
  1062.     for (i=0 ; i<sprout->numframes ; i++)
  1063.     {
  1064.         sprout->frames[i].width = LittleLong (sprin->frames[i].width);
  1065.         sprout->frames[i].height = LittleLong (sprin->frames[i].height);
  1066.         sprout->frames[i].origin_x = LittleLong (sprin->frames[i].origin_x);
  1067.         sprout->frames[i].origin_y = LittleLong (sprin->frames[i].origin_y);
  1068.         memcpy (sprout->frames[i].name, sprin->frames[i].name, MAX_SKINNAME);
  1069.         mod->skins[i] = GL_FindImage (sprout->frames[i].name,
  1070.             it_sprite);
  1071.     }
  1072.  
  1073.     mod->type = mod_sprite;
  1074. }
  1075.  
  1076. //=============================================================================
  1077.  
  1078. /*
  1079. @@@@@@@@@@@@@@@@@@@@@
  1080. R_BeginRegistration
  1081.  
  1082. Specifies the model that will be used as the world
  1083. @@@@@@@@@@@@@@@@@@@@@
  1084. */
  1085. void R_BeginRegistration (char *model)
  1086. {
  1087.     char    fullname[MAX_QPATH];
  1088.     cvar_t    *flushmap;
  1089.  
  1090.     registration_sequence++;
  1091.     r_oldviewcluster = -1;        // force markleafs
  1092.  
  1093.     Com_sprintf (fullname, sizeof(fullname), "maps/%s.bsp", model);
  1094.  
  1095.     // explicitly free the old map if different
  1096.     // this guarantees that mod_known[0] is the world map
  1097.     flushmap = Cvar_Get ("flushmap", "0", 0);
  1098.     if ( strcmp(mod_known[0].name, fullname) || flushmap->value)
  1099.         Mod_Free (&mod_known[0]);
  1100.     r_worldmodel = Mod_ForName(fullname, true);
  1101.  
  1102.     r_viewcluster = -1;
  1103. }
  1104.  
  1105.  
  1106. /*
  1107. @@@@@@@@@@@@@@@@@@@@@
  1108. R_RegisterModel
  1109.  
  1110. @@@@@@@@@@@@@@@@@@@@@
  1111. */
  1112. struct model_s *R_RegisterModel (char *name)
  1113. {
  1114.     model_t    *mod;
  1115.     int        i;
  1116.     dsprite_t    *sprout;
  1117.     dmdl_t        *pheader;
  1118.  
  1119.     mod = Mod_ForName (name, false);
  1120.     if (mod)
  1121.     {
  1122.         mod->registration_sequence = registration_sequence;
  1123.  
  1124.         // register any images used by the models
  1125.         if (mod->type == mod_sprite)
  1126.         {
  1127.             sprout = (dsprite_t *)mod->extradata;
  1128.             for (i=0 ; i<sprout->numframes ; i++)
  1129.                 mod->skins[i] = GL_FindImage (sprout->frames[i].name, it_sprite);
  1130.         }
  1131.         else if (mod->type == mod_alias)
  1132.         {
  1133.             pheader = (dmdl_t *)mod->extradata;
  1134.             for (i=0 ; i<pheader->num_skins ; i++)
  1135.                 mod->skins[i] = GL_FindImage ((char *)pheader + pheader->ofs_skins + i*MAX_SKINNAME, it_skin);
  1136. //PGM
  1137.             mod->numframes = pheader->num_frames;
  1138. //PGM
  1139.         }
  1140.         else if (mod->type == mod_brush)
  1141.         {
  1142.             for (i=0 ; i<mod->numtexinfo ; i++)
  1143.                 mod->texinfo[i].image->registration_sequence = registration_sequence;
  1144.         }
  1145.     }
  1146.     return mod;
  1147. }
  1148.  
  1149.  
  1150. /*
  1151. @@@@@@@@@@@@@@@@@@@@@
  1152. R_EndRegistration
  1153.  
  1154. @@@@@@@@@@@@@@@@@@@@@
  1155. */
  1156. void R_EndRegistration (void)
  1157. {
  1158.     int        i;
  1159.     model_t    *mod;
  1160.  
  1161.     for (i=0, mod=mod_known ; i<mod_numknown ; i++, mod++)
  1162.     {
  1163.         if (!mod->name[0])
  1164.             continue;
  1165.         if (mod->registration_sequence != registration_sequence)
  1166.         {    // don't need this model
  1167.             Mod_Free (mod);
  1168.         }
  1169.     }
  1170.  
  1171.     GL_FreeUnusedImages ();
  1172. }
  1173.  
  1174.  
  1175. //=============================================================================
  1176.  
  1177.  
  1178. /*
  1179. ================
  1180. Mod_Free
  1181. ================
  1182. */
  1183. void Mod_Free (model_t *mod)
  1184. {
  1185.     Hunk_Free (mod->extradata);
  1186.     memset (mod, 0, sizeof(*mod));
  1187. }
  1188.  
  1189. /*
  1190. ================
  1191. Mod_FreeAll
  1192. ================
  1193. */
  1194. void Mod_FreeAll (void)
  1195. {
  1196.     int        i;
  1197.  
  1198.     for (i=0 ; i<mod_numknown ; i++)
  1199.     {
  1200.         if (mod_known[i].extradatasize)
  1201.             Mod_Free (&mod_known[i]);
  1202.     }
  1203. }
  1204.